﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using SCMS.CoreBusinessLogic.Web;
using SCMS.UI.Models;
using SCMS.CoreBusinessLogic.Request4Advance;
using SCMS.CoreBusinessLogic.OrderRequest;
using SCMS.CoreBusinessLogic.TenderAnalysis;
using SCMS.Model;
using SCMS.CoreBusinessLogic.PurchaseOrder;
using SCMS.CoreBusinessLogic.Request4Payment;
using SCMS.UI.GeneralHelper;
using System.Data.Objects.DataClasses;
using SCMS.CoreBusinessLogic.Security;
using SCMS.CoreBusinessLogic.ActionFilters;
using SCMS.CoreBusinessLogic.StaffServices;
using SCMS.CoreBusinessLogic.NotificationsManager;
using SCMS.Resource;

namespace SCMS.UI.Controllers
{
    [MyException]
    public class Request4AdvanceController : PortalBaseController
    {
        private IRequest4Advance R4AService;
        private IOrderRequest ORService;
        private ITAnalysisService TAService;
        private IPurchaseOrderService POservice;
        private IRequest4PaymentService R4PSevice;
        private IStaffService staffService;
        private INotificationService notificationService;

        public Request4AdvanceController(IPermissionService permissionService, IRequest4Advance R4AService, IOrderRequest ORService, IStaffService staffService,
            ITAnalysisService TAService, IPurchaseOrderService POservice, IRequest4PaymentService R4PSevice, IUserContext userContext,
            INotificationService notificationService)
            : base(userContext, permissionService)
        {
            this.R4AService = R4AService;
            this.ORService = ORService;
            this.TAService = TAService;
            this.POservice = POservice;
            this.R4PSevice = R4PSevice;
            this.staffService = staffService;
            this.notificationService = notificationService;
        }

        //
        // GET: /Request4Advance/

        public ActionResult Index()
        {
            return View();
        }

        public ActionResult CreateRFA()
        {
            try
            {
                Models.AdvanceRequestModel model = new AdvanceRequestModel();
                model.RefNumber = string.Format("--{0}--", Resources.Global_String_NewRFA);
                InitRFALists(model);
                model.PaidTo = currentStaff.Id;
                model.RequestDate = DateTime.Today;
                return View("CreateRFA", model);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public ActionResult EditRFA(Guid Id)
        {
            AdvanceRequest entity = R4AService.GetRFAById(Id);
            AdvanceRequestModel model = AdvanceRequestExtension.ToModel(entity);
            InitRFALists(model);
            return View("CreateRFA", model);
        }

        public ActionResult DeleteRFA(Guid Id)
        {
            R4AService.DeleteRFA(Id);
            return ViewR4A();
        }

        private void InitRFALists(Models.AdvanceRequestModel model)
        {
            model.Currencies = new SelectList(ORService.GetCurrencies(countryProg.Id), "Id", "ShortName");
            model.StaffList = new SelectList(staffService.GetStaffByCountryProgramme(countryProg.Id), "StaffId", "StaffName");
            model.PaymentTypes = new SelectList(R4PSevice.GetPaymentType(countryProg.Id), "Id", "Description");
            model.PaymentTerms = new SelectList(TAService.GetPaymentTerms(countryProg.Id), "Id", "Description");
        }

        public ActionResult SaveR4A(Models.AdvanceRequestModel model)
        {
            Model.AdvanceRequest entityRFA;
            if (model.Id == Guid.Empty)
            {
                model.Id = Guid.NewGuid();
                entityRFA = AdvanceRequestExtension.ToEntity(model);
                entityRFA.CountryProgrammeId = countryProg.Id;
                entityRFA.PreparedOn = DateTime.Now;
                entityRFA.PreparedBy = currentStaff.Id;
                entityRFA.IsAuthorized = entityRFA.IsReviewed = entityRFA.IsRejected = entityRFA.IsSubmitted = false;
            }
            else
                UpdateRFA(out entityRFA, model);
            R4AService.SaveRFA(entityRFA);
            return LoadRFADetails(entityRFA);
        }

        public ActionResult LoadRFADetails(Guid Id)
        {
            AdvanceRequest entityRFA = R4AService.GetRFAById(Id);
            return LoadRFADetails(entityRFA);
        }

        /// <summary>
        /// Step 2
        /// </summary>
        /// <param name="Id"></param>
        /// <returns></returns>
        public ActionResult LoadRFADetails2(Guid Id)
        {
            AdvanceRequest entityRFA = R4AService.GetRFAById(Id);

            List<BudgetCheckResult> bcrList = R4AService.RunFundsAvailableCheck(Id);
            if (bcrList.Count > 0)
                return LoadRFADetails(entityRFA, bcrList: bcrList);//Render PO with message saying funds not sufficient
            return LoadRFADetails(entityRFA, "LoadRFADetails2");
        }

        public ActionResult SubmitRFA(AdvanceRequestModel model)
        {
            AdvanceRequest entity = R4AService.GetRFAById(model.Id);
            entity.Description = model.Description;
            entity.DocDescription = model.DocDescription;
            entity.Remarks = model.Remarks;
            entity.PreparedOn = DateTime.Now;
            entity.IsSubmitted = true;
            entity.RefNumber = R4AService.GenerateUniquNumber(countryProg);
            R4AService.SaveRFA(entity);
            //Send notification            
            notificationService.SendToAppropriateApprover(NotificationHelper.rfaCode, NotificationHelper.reviewCode, entity.Id);
            return ViewR4A();
        }

        private void UpdateRFA(out AdvanceRequest rfa, AdvanceRequestModel model)
        {
            rfa = R4AService.GetRFAById(model.Id);
            rfa.RequestDate = model.RequestDate;
            rfa.CurrencyId = model.CurrencyId;
            rfa.PaymentTermId = model.PaymentTermId;
            rfa.PaymentTypeId = model.PaymentTypeId;
            rfa.PaidTo = model.PaidTo;
            rfa.Subject = model.Subject;
        }

        private ActionResult LoadRFADetails(Model.AdvanceRequest entityRFA, string viewName = "LoadRFADetails", List<BudgetCheckResult> bcrList = null)
        {
            entityRFA = R4AService.GetRFAById(entityRFA.Id);
            Models.AdvanceRequestModel model = AdvanceRequestExtension.ToModel(entityRFA);
            //Build BudgetLine Lists
            List<Models.AdvanceRequestBLModel> paymentDetails = new List<AdvanceRequestBLModel>();
            List<Model.AdvanceRequestBudgetLine> rfaBudgetLines = R4AService.GetRFADetails(entityRFA.Id);
            foreach (var rfaBL in rfaBudgetLines)
            {
                var rfaBLModel = AdvanceRequestBLExtension.ToModel(rfaBL);
                paymentDetails.Add(rfaBLModel);
            }
            model.PaymentDetails = paymentDetails;
            model.BudgetCheckResults = bcrList;
            InitRFALists(model);
            //Set display fields
            return View(viewName, model);
        }

        public ActionResult CreateRFADetail(Guid Id)
        {
            AdvanceRequestBLModel model = new AdvanceRequestBLModel();
            model.AdvanceRequestId = Id;
            List<ProjectDonor> pdList = ORService.GetProjectNos(countryProg.Id);
            model.ProjectNos = new SelectList(pdList, "Id", "ProjectNumber");
            model.Id = Guid.Empty;
            model.AdvanceOptions = new SelectList(R4AService.GetAdvanceOptions(), "Id", "Name");
            if (pdList.Count > 0)
            {
                model.BudgetLines = new SelectList(ORService.GetProjectBugdetLines(pdList[0].Id), "Id", "Description");
            }
            return View("CreateRFADetail", model);
        }

        public ActionResult EditRFADetail(Guid Id)
        {
            AdvanceRequestBudgetLine entity = R4AService.GetRFABLById(Id);
            AdvanceRequestBLModel model = AdvanceRequestBLExtension.ToModel(entity);
            model.Id = Id;
            model.ProjectNos = new SelectList(ORService.GetProjectNos(countryProg.Id), "Id", "ProjectNumber", entity.ProjectBudget.BudgetCategory.ProjectDonorId);
            model.BudgetLines = new SelectList(ORService.GetProjectBugdetLines(entity.ProjectBudget.BudgetCategory.ProjectDonor.Id), "Id", "Description", entity.BudgetLineId);
            model.AdvanceOptions = new SelectList(R4AService.GetAdvanceOptions(), "Id", "Name");
            return View("CreateRFADetail", model);
        }

        public ActionResult DeleteRFADetail(Guid Id)
        {
            AdvanceRequestBudgetLine entity = R4AService.GetRFABLById(Id);
            R4AService.DeleteRFADetail(entity.Id);
            return LoadRFADetails(entity.AdvanceRequest);
        }

        public ActionResult SaveRFADetail(AdvanceRequestBLModel model)
        {
            try
            {
                Model.AdvanceRequestBudgetLine entityRFABL;
                if (model.Id == Guid.Empty || model.Id == model.AdvanceRequestId)
                    model.Id = Guid.NewGuid();
                entityRFABL = AdvanceRequestBLExtension.ToEntity(model);
                R4AService.SaveRFADetail(entityRFABL);
                AdvanceRequest entityRFA = R4AService.GetRFAById(model.AdvanceRequestId);
                return LoadRFADetails(entityRFA);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public ActionResult ViewR4A()
        {
            List<AdvanceRequestModel> model = new List<AdvanceRequestModel>();
            List<AdvanceRequest> PR = R4AService.GetAdvanceRequests(countryProg.Id);
            foreach (AdvanceRequest item in PR)
            {
                //if (!item.IsSubmitted)
                //    continue;
                model.Add(AdvanceRequestExtension.ToModel(item));
            }
            return View("ViewR4A", model);
        }

        public ActionResult ViewRADetails(Guid id, bool checkPost = false)
        {
            AdvanceRequest entityRFA = R4AService.GetRFAById(id);
            AdvanceRequestModel model = AdvanceRequestExtension.ToModel(entityRFA);
            List<Models.AdvanceRequestBLModel> paymentDetails = new List<AdvanceRequestBLModel>();
            List<Model.AdvanceRequestBudgetLine> rfaBudgetLines = R4AService.GetRFADetails(entityRFA.Id);
            foreach (var rfaBL in rfaBudgetLines)
            {
                var rfaBLModel = AdvanceRequestBLExtension.ToModel(rfaBL);
                paymentDetails.Add(rfaBLModel);
            }
            model.PaymentDetails = paymentDetails;            
            
            //Manage approval link
            string actionType = null;
            if (model.IsReviewed && !model.IsAuthorized)
                actionType = NotificationHelper.authorizationCode;
            else if (model.IsSubmitted && !model.IsReviewed)
                actionType = NotificationHelper.reviewCode;
            if (actionType != null)
                model.CanApprove = notificationService.CanApprove(currentUser, NotificationHelper.rfaCode, actionType, model.Id);
            else
                model.CanApprove = false;

            //Manage Can Post Button
            model.CanEdit = (!model.IsSubmitted && !model.IsRejected && model.PreparedBy == currentStaff.Id) ||
                    (model.IsSubmitted && model.IsRejected && !model.IsReviewed && model.PreparedBy == currentStaff.Id);

            //Manage Post Funds Button
            if (userContext.HasPermission(StandardPermissionProvider.RequestForAdvancePostFunds) && checkPost)
                foreach (var rfa in R4AService.GetAdvanceRequestsForPosting(countryProg.Id, currentUser))
                {
                    if (rfa.Id.Equals(model.Id))
                    {
                        model.CanPostFunds = true;
                        break;
                    }
                }

            return View(model);
        }
    }
}
